package com.mpgame.database.redis.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.mpgame.database.redis.model.RedisCommand;
import com.mpgame.database.redis.model.UserTokenInfo;
import com.mpgame.database.redis.model.enums.CommandType;
import com.mpgame.utils.Log;

import io.lettuce.core.TransactionResult;

public class PlayerOnlineUtil {
    private PlayerOnlineUtil() {
    }
    /** 得到对应ID玩家的UserTokenInfo信息 */
    public static UserTokenInfo getUserTokenInfoFromAccountId(int accountId) {
        return TokenUtil.getUserTokenInfoFromAccountId(accountId);
    }
    /** 将指定ID玩家添加至在线列表（整型重载） */
    public static void addPlayerToOnlineList(int accountId) {
        RedisUtil.sadd("online_players", String.valueOf(accountId));
    }
    /** 将指定ID玩家添加至在线列表（字符串重载） */
    public static void addPlayerToOnlineList(String accountId) {
        RedisUtil.sadd("online_players", accountId);
    }
    /** 将指定ID玩家从在线列表移除（整型重载） */
    public static void removePlayerFromOnlineList(int accountId) {
        RedisUtil.srem("online_players", String.valueOf(accountId));
    }
    /** 将指定ID玩家从在线列表移除（字符串重载） */
    public static void removePlayerFromOnlineList(String accountId) {
        RedisUtil.srem("online_players", accountId);
    }

    /** 得到所有在线玩家Redis中的UserTokenInfo信息 */
    public static List<UserTokenInfo> getAllOnlinePlayerInfos() {
        List<UserTokenInfo> playerInfos = new ArrayList<>();

        Set<String> onlinePlayerIds = RedisUtil.smembers("online_players");
        if(onlinePlayerIds == null || onlinePlayerIds.isEmpty()){
            return playerInfos;
        }

        List<RedisCommand> cmdList = new ArrayList<>(onlinePlayerIds.size());
        for(String playerIdStr : onlinePlayerIds){
            try{
                String key = TokenUtil.getSessionPrefix(playerIdStr);
                cmdList.add(new RedisCommand(CommandType.HGETALL, key, null));
            }catch(Exception e){
                Log.warn("构建指令列表出错：" + e.getMessage());
            }
        }

        TransactionResult results = RedisUtil.pipeline(cmdList);

        for(int i = 0; i < cmdList.size(); i++){
            Object raw = results.get(i);
            if(raw == null){
                continue;
            }

            if(!(raw instanceof Map)){
                Log.warn("第 " + i + " 条结果不是Map类型，实际=" + raw.getClass());
                continue;
            }
            @SuppressWarnings("unchecked")
            Map<String, String> hash = (Map<String, String>)raw;
            if(hash.isEmpty()){
                continue;
            }

            UserTokenInfo info = convertMapToUserTokenInfo(hash);
            if(info != null){
                playerInfos.add(info);
            }
        }
        return playerInfos;
    }

    /** 得到在线玩家数目 */
    public static long getOnlinePlayerCount() {
        try {
            Long count = RedisUtil.scard("online_players");
            return count != null ? count : 0;
        } catch (Exception e) {
            Log.err("获取在线玩家数量失败：" + e.getMessage());
            return 0;
        }
    }
    /** 指定ID玩家是否在线 */
    public static boolean isPlayerOnline(int accountId) {
        try {
            Boolean isOnline = RedisUtil.sismember("online_players", String.valueOf(accountId));
            return isOnline != null ? isOnline : false;
        } catch (Exception e) {
            Log.err("检查玩家在线状态失败：" + e.getMessage());
            return false;
        }
    }
    /** 获取指定ID玩家的玩家昵称 */
    public static String getPlayerName(int accountId){
        try{
            String sessionKey = TokenUtil.getSessionPrefix(accountId);
            String nickname = RedisUtil.hget(sessionKey, "nickname");
            return nickname;
        }catch(Exception e){
            Log.err("获取玩家昵称失败：" + e.getMessage());
            return null;
        }
    }
    /** 获取指定ID玩家的玩家昵称 */
    public static String getPlayerName(String accountId){
        return getPlayerName(Integer.parseInt(accountId));
    }

    private static UserTokenInfo convertMapToUserTokenInfo(Map<String, String> hash){
        try{
            UserTokenInfo uti = new UserTokenInfo();
            uti.setAccountId(Integer.parseInt(hash.getOrDefault("accountId", "0")));
            uti.setUsername(hash.getOrDefault("username", "null"));
            uti.setNickname(hash.getOrDefault("nickname", "null"));
            uti.setToken(hash.getOrDefault("token", "null"));
            uti.setLastLoginTimestamp(Long.parseLong(hash.getOrDefault("lastLoginTimestamp", "0")));
            uti.setLastActiveTimestamp(Long.parseLong(hash.getOrDefault("lastActiveTimestamp", "0")));
            uti.setPosX(Float.parseFloat(hash.getOrDefault("posX", "0")));
            uti.setPosY(Float.parseFloat(hash.getOrDefault("posY", "0")));
            uti.setSceneId(Integer.parseInt(hash.getOrDefault("sceneId", "0")));
            return uti;
        }catch(Exception e){
            Log.warn("map -> userTokenInfo失败，map=" + hash + "，错误消息：" + e.getMessage());
            return null;
        }
    }
}
